package com.nt.train.processor;

import com.nt.train.annotation.CoreAnnotation;
import com.nt.train.annotation.EnableCustomImport;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * @author hlf
 * @version 1.0
 * @date 2022/8/12 11:16
 */
public class MyImportBeanDefinitionRegistrar2 implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

    private Environment environment;

    private ResourceLoader resourceLoader;

    @SneakyThrows
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean enableCustomImport = importingClassMetadata.hasAnnotation(EnableCustomImport.class.getName());
        System.out.println("enableCustomImport:"+enableCustomImport);
        //@Import不是在这个EnableCustomImport注解上的不执行
        if (!enableCustomImport) {
            return;
        }

        // useDefaultFilters = false,即第二个参数 表示不扫描 @Component、@ManagedBean、@Named 注解标注的类
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false,
                environment, resourceLoader);
        scanner.addIncludeFilter(new AnnotationTypeFilter(CoreAnnotation.class));

        Map<String, Object> annotationAttributesMap = importingClassMetadata.getAnnotationAttributes(EnableCustomImport.class.getName());

        System.out.println("annotationAttributesMap:"+annotationAttributesMap);

        AnnotationAttributes annotationAttributes = Optional.ofNullable(AnnotationAttributes.fromMap(annotationAttributesMap))
                .orElseGet(AnnotationAttributes::new);

        // 获取需要扫描的包
        String[] packages = retrievePackagesName(importingClassMetadata, annotationAttributes);
        // 扫描包
        for (String needScanPackage : packages) {
            Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(needScanPackage);
            try {
                registerCandidateComponents(registry, candidateComponents);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 重新注册 BeanDefinition bean
     */
    private void registerCandidateComponents(BeanDefinitionRegistry registry, Set<BeanDefinition> candidateComponents)
            throws ClassNotFoundException {
        for (BeanDefinition candidateComponent : candidateComponents) {
            if (candidateComponent instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) candidateComponent;
                AnnotationMetadata annotationMetadata = annotatedBeanDefinition.getMetadata();
                Map<String, Object> customImportAnnotationAttributesMap = annotationMetadata.getAnnotationAttributes(
                        CoreAnnotation.class.getName());
                AnnotationAttributes customImportAnnotationAttributes = Optional.ofNullable(AnnotationAttributes.
                        fromMap(customImportAnnotationAttributesMap)).orElseGet(AnnotationAttributes::new);//获取注解里的值
                String[] values = customImportAnnotationAttributes.getStringArray("value");
                String className = annotationMetadata.getClassName();
                Class<?> clazzName = Class.forName(className);
                Arrays.asList(values).forEach(m ->{
                    RootBeanDefinition mbean = null;
                    try {
                        mbean = new RootBeanDefinition(clazzName);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    registry.registerBeanDefinition(m, mbean);
                });
            }
        }
    }

    /**
     * 获取需要扫描的包
     */
    private String[] retrievePackagesName(AnnotationMetadata annotationMetadata, AnnotationAttributes annotationAttributes) {
        String[] packages = annotationAttributes.getStringArray("packages");
        if (packages.length > 0) {
            return packages;
        }
        //如果不存在，则默认第一个包开始
        String className = annotationMetadata.getClassName();
        return new String[]{className.split("\\.")[0]};
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}